[Chapter 21] 21.3 Set Up MX Records
Author: Bryan Costales & Eric Allman
Date: 1999-01-06T19:28:23Z

#

| Chapter 21 DNS and sendmail |

## 21.3 Set Up MX Records

An MX record is simply the method used by DNS to route mail bound for one machine to another instead. An MX record is created by a single line in one of your named(8) files:

>     hostA    IN      MX 10 hostB

This line says that all mail destined for `hostA` in your domain should instead be delivered to `hostB` in your domain. The `IN` says that this is an Internet-type record, and the `10` is the cost [11] for using this MX record.

> [11] Technically, this field is called the preference. We use cost to clarify that lower values are preferable, whereas preference wrongly connotes that higher values are preferable.

An MX record may point to another host or to the original host:

>     hostA    IN      MX 0 hostA

This line says that mail for `hostA` will be delivered to `hostA`. Such records may seem redundant, but they are not. We'll cover why shortly.

A host can have multiple MX records (one pointing to itself or not):

>     hostA   IN      MX 0  hostA
>             IN      MX 10 hostB

Here, `hostA` has the lowest cost (`0` versus `10` for `hostB`), so delivery will be attempted to itself first. If `hostA` is down, delivery will be attempted to `hostB` host instead.

Usually, MX records point to hosts inside the same domain. Therefore managing them does not require the cooperation of others. But it is legal for MX records to point to hosts in different domains:

>     hostA   IN      MX 0  hostA
>             IN      MX 10  host.other.domain.

Here, you must contact the administrator at `other.domain` and obtain permission before creating this MX record. We cover this concept in more detail when we discuss disaster preparation later in this chapter.

Although MX records are usually straightforward, there can be a few problems associated with them.

### 21.3.1 MX Must Point to an A Record

The A record for a host is a line that gives the host's IP address.

>     hostC  IN     A   123.45.67.8

Here, `hostC` is the host's name. The `IN` says this is an Internet-type record. The `A` marks this as an A record. The `123.45.67.8` is the IP address for the host `hostC`.

An MX record must point to a hostname that has an A record. To illustrate, consider the following:

>     hostA  IN     MX  10 hostB            illegal
>            IN     MX  20 hostC
>     hostB  IN     MX  10 hostC
>     hostC  IN     A   123.45.67.8

Note that `hostB` lacks an A record but `hostC` has one. It is illegal to point an MX record at a host that lacks an A record. Therefore the first line above is illegal, whereas the second line is legal.

Although such a mistake is difficult to make when maintaining your own domain tables, it can easily happen to you if you rely on a name server in someone else's domain, as shown:

>     hostA    IN     MX  10 mail.other.domain.

The other administrator might, for example, retire the machine `mail` and replace its A record with an MX record that points to a different machine. Unless you are notified of the change, your MX record will suddenly become illegal.

### 21.3.2 MX to CNAME Causes Extra Lookups

The sendmail program is frequently more forgiving than other MTAs because it accepts an MX record that points to a CNAME record. The presumption is that, eventually, the CNAME will correctly point to an A record. But beware, this kind of indirection can cost additional DNS lookups. Consider this example of an exceptionally bad setup:

>     hostA    IN     MX  10 mailhub
>     mailhub  IN     CNAME  nfsmast
>     nfsmast  IN     CNAME  hostB
>     hostB    IN     A 123.45.67.89

First, sendmail looks up `hostA` and gets an MX record pointing to `mailhub`. Since there is only a single MX record, sendmail considers `mailhub` to be official. Next, `mailhub` is looked up to find an A record (IP address), but instead a CNAME (`nfsmast`) is returned. Now sendmail must look up the CNAME `nfsmast` to find its A record. But again a CNAME is returned instead of an A record. So sendmail must again look for an A record (this time with `hostB`). Finally, sendmail succeeds by finding the A record for `hostB`, but only after a few too many lookups.

The correct way to form the above DNS file entries is as follows:

>     hostA    IN     MX  10 hostB
>     mailhub  IN     CNAME  hostB
>     nfsmast  IN     CNAME  hostB
>     hostB    IN     A 123.45.67.89

In general, try to construct DNS records in such a way that the fewest lookups are required to resolve any A or MX records.

### 21.3.3 MX Records Are Nonrecursive

Consider the following MX setup, which causes all mail for `hostA` to be sent to `hostB` and all mail for `hostB` to be sent to `hostB`, or to `hostC` if `hostB` is down: [12]

> [12] We are fudging for the sake of simplicity. Here, we assume that all the hosts also have A records.

>     hostA   IN     MX  10 hostB
>     hostB   IN     MX  10 hostB
>             IN     MX  20 hostC

One might expect sendmail to be smart and deliver mail for `hostA` to `hostC` if `hostB` is down. But sendmail won't do that. It does not try to recursively look for additional MX records. If it did, it could get hopelessly entangled in MX loops. Consider the following:

>     hostA   IN     MX  10 hostB
>     hostB   IN     MX  10 hostB
>             IN     MX  20 hostC
>     hostC   IN     MX  10 hostA      potential loop

If your intention is to have `hostA` MX to two other hosts, then you must state that explicitly:

>     hostA   IN     MX  10 hostB
>             IN     MX  20 hostC
>     hostB   IN     MX  10 hostB
>             IN     MX  20 hostC

Another reason sendmail refuses to follow MX records beyond the target host is that costs in such a situation are undefined. Consider the example with the potential loop above. What is the cost of `hostA` when MX'd by `hostB` to `hostC`? Should it be the minimum of 10, the maximum of 20, the mean of 15, or the sum of 30?

### 21.3.4 Wildcard MX Records

Wildcard MX records provide a shorthand for MX'ing many hosts with a single MX record:

>     *.dc.gov.       IN  MX  10 hostB

This says that any host in the domain `.dc.gov` (where that host doesn't have any record of its own) should have its mail forwarded to `hostB`.

>     ; domain is .dc.gov
>     *.dc.gov.       IN  MX  10 hostB
>     hostA           IN  MX  10 hostC
>     hostB           IN  A   123.45.67.8

Here, mail to `hostD` (no record at all) will be forwarded to `hostB`. But the wildcard MX record will be ignored for `hostA` and `hostB`, because each has its own record.

Care must be exercised in setting up wildcard MX records. It is easy to create ambiguous situations that DNS may not be be able to handle correctly. Consider the following, for example:

>     ; domain is sub.dc.gov
>     *.dc.gov.       IN  MX  10 hostB.dc.gov.
>     *.sub.dc.gov.   IN  MX  10 hostC.dc.gov.

Here, an unqualified name such as just plain `hostD` matches both wildcard records. This is ambiguous, so DNS automatically picks the most complete one (`*.sub.dc.gov.`) and supplies that MX record to sendmail.

One compelling weakness of wildcard MX records is that they match any hostname at all, even for machines that don't exist:

>     ; domain is sub.dc.gov
>     *.dc.gov.       IN  MX  10 hostB.dc.gov.

Here, mail to foo.dc.gov will be forwarded to `hostB.dc.gov`, even if there is no host foo in that domain.

Wildcard MX records almost never have any appropriate use on the Internet. They are often misunderstood and are often used just to save the effort of typing hundreds of MX records. They do, however, have legitimate uses behind firewall machines and on non-Internet networks.

### 21.3.5 What? They Ignore MX Records?

Many older MTAs on the network ignore MX records, and some Sun sites wrongly run the non-MX version of sendmail (that is, they should use /usr/lib/sendmail.mx). Because of this, you will occasionally find some sites that insist on sending mail to a host even though that host has been explicitly MX'd to another.

To illustrate why this is bad, consider a UUCP host that has only an MX record. It has no A record because it is not on the network:

>     uuhost   IN    MX  10 uucpserver

Here, mail to `uuhost` will be sent to `uucpserver`, which will forward the message to `uuhost` with UUCP software. An attempt to ignore this MX record will fail because `uuhost` has no other records. Similar problems can arise for printers with direct network connections, terminal servers, and even workstations that don't run an SMTP daemon such as sendmail.

If you believe in DNS and disdain sites that don't, you can simply ignore the offending sites. In this case the mail will fail if your MX'd host doesn't run a sendmail daemon (or another MTA). This is not as nasty as it sounds. There is actually considerable support for this approach; failure to obey MX records is a clear violation of published network protocols. RFC1123, Host Requirements, section 5.3.5, notes that obeying MX records is mandatory.

On the other hand, if you want to ensure that all mail is received, even on a workstation whose mail is MX'd elsewhere, you can run the sendmail daemon on every machine.

### 21.3.6 Caching MX Records

Although you are not required to have MX records for all hosts, there is good reason to consider doing so. To illustrate, consider the following host that only has an A record:

>     hostB           IN  A   123.45.67.8

When sendmail first looks up this host, it asks the local name server for all records. Because there is only an A record, that is all it gets.

But note that asking for all records caused the local name server to cache the information. The next time sendmail looks up this same host, the local name server will return the A record from its cache. This is faster and reduces Internet traffic. The cached information is "nonauthoritative" (because it is a copy) and includes no MX records (because there are none).

When sendmail gets a nonauthoritative reply that lacks MX records, it is forced to do another DNS lookup. This time, it specifically asks for MX records. In this case there are none, so it gets none.

Because `hostB` lacks an MX record, sendmail performs a DNS lookup each and every time mail is sent to that host. If `hostB` were a major mail-receiving site, its lack of an MX record would be causing many sendmail programs, all over the world, to waste network bandwidth with otherwise useless DNS lookups.

We strongly recommend that every host on the Internet have at least one MX record. As a minimum, it can simply point to itself with a 0 cost:

>     hostB           IN  A   123.45.67.8
>                     IN  MX  0 hostB

This will not change how mail is routed to `hostB` but will reduce the number of DNS lookups required.

### 21.3.7 Ambiguous MX Records

RFC974 leaves the treatment of ambiguous MX records to the implementor's discretion. This has generated much debate in sendmail circles. Consider the following:

>     foo    IN MX 10 hostA
>     foo    IN MX 20 hostB         mail from hostB to foo
>     foo    IN MX 30 hostC

When mail is sent from a host (`hostB`) that is an MX record for the receiving host (`foo`), all MX records that have a cost equal to or greater than that of `hostB` must be discarded. The mail is then delivered to the remaining MX host with the lowest cost (`hostA`). This is a sensible rule, because it prevents `hostB` from wrongly trying to deliver to itself.

It is possible to configure `hostB` so that it views the name `foo` as a synonym for its own name. Such a configuration results in `hostB` never looking up any MX records because it recognizes mail to `foo` as local.

But what should happen if `hostB` does not recognize `foo` as local and if there is no `hostA`?

>                                   no hostA
>     foo    IN MX 20 hostB         mail from hostB to foo
>     foo    IN MX 30 hostC

Again, RFC974 says that when mail is being sent from a host (`hostB`) that is an MX record for the receiving host (`foo`), all MX records that have a cost equal to or greater than that of `hostB` must be discarded. In this example that leaves zero MX records. Three courses of action are now open to sendmail, but RFC974 doesn't say which it should use:

- Assume that this is an error condition. Clearly, hostB should have been configured to recognize foo as local. It didn't (hence the MX lookup and discarding in the first place), so it must not have known what it was doing. V8 sendmail with the `TryNullMXList` (`w`) option (see Section 34.8.71, TryNullMXList (w)) not set (undeclared or declared as false) will bounce the mail message.

- Look to see whether foo has an A record. If it does, go ahead and try to deliver the mail message directly to foo. If it lacks an A record, bounce the message. This approach runs the risk that foo may not be configured to properly accept mail (thus causing mail to disappear down a black hole). Still, this approach may be desirable in some circumstances. V8 sendmail with the `TryNullMXList` (`w`) option (see Section 34.8.71) set always tries to connect to foo. [13]

  > [13] As does the UIUC version of IDA sendmail. Other versions of IDA (such as KJS) do not.

- Assume (even though it has not been configured to do so) that foo should be treated as local to hostB. No version of sendmail makes this assumption.

This situation is not an idle exercise. Consider the MX record for `uuhost` presented in the previous section:

>     uuhost   IN    MX  10 uucpserver

Here, `uuhost` has no A record, because it is connected to `uucpserver` via a dial-up line. If `uucpserver` is not configured to recognize `uuhost` as one of its UUCP clients, and if mail is sent from `uucpserver` to `uuhost`, it will query DNS and get itself as the MX record for `uuhost`. As we have shown, that MX record is discarded, and an ambiguous situation has developed.

21.2 How sendmail Uses DNS |  | 21.4 How to Use nslookup